package fi.bluepill.server.rest;

import fi.bluepill.server.model.Keystore;
import fi.bluepill.server.model.UserAccount;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ObjectNode;
import org.scribe.builder.ServiceBuilder;
import org.scribe.builder.api.TwitterApi;
import org.scribe.model.*;
import org.scribe.oauth.OAuthService;
import rip.core.Transactional;

import javax.servlet.http.Cookie;
import java.io.IOException;

public class TwitterService extends BluepillService {
    @Transactional
    public void callback() {
        assertAuthentication();

        String json = base64Decode(cookie("bluepillData"));
        JsonNode input = null;

        response.addCookie(new Cookie("bluepillData", ""));

        try {
             input = json().readTree(json);
        } catch (IOException e) {
            e.printStackTrace();
            error(e.getMessage());
            return;
        }

        UserAccount user = user(input.get("userId").asText());
        Keystore keystore = user.getKeystore();

        OAuthService service = new ServiceBuilder()
                .provider(TwitterApi.class)
                .apiKey(env("twitter.api.key"))
                .apiSecret(env("twitter.api.secret"))
                .debug()
                .build();

        Verifier verifier = new Verifier(queryParameter("oauth_verifier"));

        Token accessToken = service.getAccessToken(new Token(keystore.getTwitterRequestToken(), keystore.getTwitterRequestTokenSecret()), verifier);

        keystore.setTwitterAccessToken(accessToken.getToken());
        keystore.setTwitterAccessTokenSecret(accessToken.getSecret());

        user.setKeystore(keystore);
        jpa().merge(user);

        sendMessage(input.get("message").getTextValue(), input.get("lon").getTextValue(), input.get("lat").getTextValue(), user, service);
    }

    @Transactional
    public void publish() {
        assertAuthentication();

        TwitterPublishMessage input = read(TwitterPublishMessage.class);

        UserAccount user = user(userId());
        Keystore keystore = user.getKeystore();

        OAuthService service = new ServiceBuilder()
                .provider(TwitterApi.class)
                .apiKey(env("twitter.api.key"))
                .apiSecret(env("twitter.api.secret"))
                .callback(env("twitter.callback.url"))
                .debug()
                .build();

        if (isEmpty(keystore.getTwitterAccessToken())) {
            Token requestToken = service.getRequestToken();

            keystore.setTwitterRequestToken(requestToken.getToken());
            keystore.setTwitterRequestTokenSecret(requestToken.getSecret());

            user.setKeystore(keystore);
            jpa().merge(user);

            String authUrl = service.getAuthorizationUrl(requestToken);

            try {
                ObjectNode oauthData = json().createObjectNode();

                oauthData.put("userId", user.getUuid());
                oauthData.put("message", input.getMessage());
                oauthData.put("lon", input.getLon());
                oauthData.put("lat", input.getLat());

                String json = json().writer().writeValueAsString(oauthData);
                response.addCookie(new Cookie("bluepillData", base64Encode(json)));
                response.sendRedirect(authUrl);
                return;
            } catch (IOException e) {
                e.printStackTrace();
                error(e.getMessage());
            }
        }

        sendMessage(input.getMessage(), input.getLon(), input.getLat(), user, service);
    }

    private void sendMessage(String message, String lon, String lat, UserAccount user, OAuthService service) {
        Keystore keystore = user.getKeystore();
        Token accessToken = new Token(keystore.getTwitterAccessToken() , keystore.getTwitterAccessTokenSecret());

        OAuthRequest request = new OAuthRequest(Verb.POST, "http://api.twitter.com/1/statuses/update.format");
        service.signRequest(accessToken, request);
        request.addBodyParameter("status", message);

        if (!isEmpty(lon))
            request.addBodyParameter("long", lon);

        if (!isEmpty(lat))
            request.addBodyParameter("lat", lat);

        Response response = request.send();

        ObjectNode m = okMessage();
        m.put("twitter_response", response.getBody());
    }

}
